package net.imagine.core;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

/**
 * <pre>
 * 多线程的图片操作服务，使用前必须指定图片处理模板template，并执行{@link #initService()}方法
 * template为{@link ImageProcessTemplate}的子类的实现类
 * 所有图片操作服务都将继承自该类，并实现{@link #execute(String, List)}。
 * </pre>
 * 
 * @author wuqh
 */
@Component("processService")
public class ImageProcessService {
	private static final Log logger = LogFactory.getLog(ImageProcessService.class);
	protected final ImageProcessTemplate template;
	protected final long timeout;
	protected final int poolSize;

	public ImageProcessService(ImageProcessTemplate template, long timeout, int poolSize) {
		this.template = template;
		this.poolSize = poolSize;
		this.timeout = timeout;
	}

	// /**
	// * 设置图片处理模板
	// *
	// * @param 图片处理模板
	// */
	// public void setTemplate(ImageProcessTemplate template) {
	// this.template = template;
	// }
	//
	// /**
	// * 设置超时时间（图片操作总用时的上限）
	// *
	// * @param 超时时间
	// */
	// public void setTimeout(long timeout) {
	// this.timeout = timeout;
	// }
	//
	// /**
	// * 设置线程池中的线程数
	// *
	// * @param 线程池中的线程数
	// */
	// public void setPoolSize(int poolSize) {
	// this.poolSize = poolSize;
	// }

	/**
	 * 执行图片的多线程处理
	 * 
	 * @param filePath
	 *            图片存放的本地目录
	 * @param tasks
	 *            图片处理任务
	 * 
	 * @return tasks中图片处理的结果
	 */
	public <E extends ImageProcessResult> List<E> execute(String filePath, List<? extends ImageProcessTask> tasks) {
		if (tasks == null || tasks.isEmpty()) {
			return null;
		}
		List<Future<E>> futures = null;
		List<ImageProcessTaskExecutor<E>> taskCallers = new ArrayList<ImageProcessTaskExecutor<E>>(tasks.size());
		for (ImageProcessTask task : tasks) {
			taskCallers.add(new ImageProcessTaskExecutor<E>(filePath, task, template));
		}
		ExecutorService imageProcessService = Executors.newFixedThreadPool(poolSize);
		try {
			futures = imageProcessService.invokeAll(taskCallers, timeout, TimeUnit.MILLISECONDS);
		} catch (InterruptedException e) {
			logger.debug("catch an InterruptedException in execute", e);
		} finally {
			imageProcessService.shutdown();
		}
		return formateResult(tasks, futures);
	}

	/**
	 * 把多线程处理的结果转换成最终的ImageProcessResult
	 * 
	 * @param futures
	 *            图片存放的本地目录
	 * 
	 * @return futures导出的处理结果
	 */
	@SuppressWarnings("unchecked")
	protected <E extends ImageProcessResult> List<E> formateResult(List<? extends ImageProcessTask> tasks, List<Future<E>> futures) {
		if (futures != null) {
			int len = futures.size();
			List<E> results = new ArrayList<E>(len);
			for(int i=0; i<len; i++) {
				Future<E> future = futures.get(i);
				E result = null;
				try {
					result = future.get();
				} catch (InterruptedException e) {
					logger.debug("catch an InterruptedException in formateResult", e);
				} catch (ExecutionException e) {
					logger.warn("throw a exception when execution", e);
				}
				if (result != null) {
					results.add(result);
				} else {
					logger.warn("the process result is null");
					E failResult = (E) new ImageProcessResult(ResultState.UNKOWN_FAILED);
					failResult.setOriginalFilename(tasks.get(i).getFilename());
					results.add(failResult);

				}
			}
			return results;
		} else {
			return null;
		}
	}
}